package com.wang.concurrency;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

//使用Lock实现生产者/消费者模式
//add/reduce一定要确保使用的是同一把锁
public class Repository {

    /*使用mutex保护condition*/
    private final Lock mutex = new ReentrantLock();
    private final Condition addCondition = mutex.newCondition();
    private final Condition reduceCondition = mutex.newCondition();    
	
	private int count;
	private int limit;	
	public int getCount() {
		return count;
	}

	public int getLimit() {
		return limit;
	}


	public Repository(int count, int limit) {
		super();
		this.count = count;
		this.limit = limit;
	}
	
	private boolean canAdd(int count){
		return this.count+count <= limit;
	}
	private boolean canReduce(int count){
		return this.count - count>=0;
	}
	
	public void add(int count){	
		try{
			//+加锁
			mutex.lock();
//			if(canAdd(count)){
//				Thread.sleep(500);
//				this.count+=count;
//				return true;
//			}			
			Thread.sleep(500);
			while(!canAdd(count)){
				System.out.printf("+... 生产者 %s  is waiting...%n", Thread.currentThread().getName());
				addCondition.await();
			}
			this.count += count;
            System.out.printf("+ %s生产成功, 当前产品数%d%n", Thread.currentThread().getName(), getCount());
            
            // 唤醒消费线程
            reduceCondition.signalAll();
						
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// + 解锁
			mutex.unlock();
		}
		
	}
	
	
	public void reduce(int count){
		try{
			//-加锁
			
			mutex.lock();
//			if(canReduce(count)){
//				Thread.sleep(500);
//				this.count -= count;
//				return true;
//			}
			Thread.sleep(500);
			while (!canReduce(count)) {
                System.out.printf("-... 消费者 %s  is waiting...%n", Thread.currentThread().getName());
                reduceCondition.await();
            }
            this.count -= count;
            System.out.printf("- %s消费成功, 当前产品数%d%n", Thread.currentThread().getName(), getCount());

            // 唤醒生产线程
            addCondition.signalAll();			
			
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// -解锁
			mutex.unlock();
		}

	}
	
	
}
